import React, { useState } from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import { DayPickerRangeController } from 'react-dates';
import dayjs from 'dayjs';
import DateRange from './../../../components/DateRange';

import notification from '@kuiper-components/notification';
import Button from '@kuiper-components/button';
import 'react-dates/initialize';
import 'react-dates/lib/css/_datepicker.css';
import Input from '@kuiper-components/input';

import { datetime } from '../../../../common/formatter';
import s from './DateRangeSelect.module.css';
import Dialog from '@knownsec/react-component/dist/Dialog';
import Form from '@knownsec/react-component/dist/Form';
import Radio from '@knownsec/react-component/dist/Radio';
import Select from '@knownsec/react-component/dist/Select';
import moment from 'moment';
import fetchjs from 'API/fetch';
import Datetime from '@knownsec/react-component/dist/Datetime';
import Progress from '@knownsec/react-component/dist/Progress';

const selectList = [
	{
		label: '当次监测',
		value: 'latest',
	},
	{
		label: '上次监测',
		value: 'previous',
	},
	{
		label: '今天',
		value: 'today',
	},
	{
		label: '昨天',
		value: 'yesterday',
	},
	{
		label: '自定义',
		value: 'scheme',
	},
];

function isBeforeDay(a, b) {
	if (!dayjs.isDayjs(a) || !dayjs.isDayjs(b)) return false;

	const aYear = a.year();
	const aMonth = a.month();

	const bYear = b.year();
	const bMonth = b.month();

	const isSameYear = aYear === bYear;
	const isSameMonth = aMonth === bMonth;

	if (isSameYear && isSameMonth) return a.date() < b.date();
	if (isSameYear) return aMonth < bMonth;
	return aYear < bYear;
}

function isInclusivelyAfterDay(a, b) {
	if (!dayjs.isDayjs(a) || !dayjs.isDayjs(b)) return false;
	return isBeforeDay(a, b);
}
export default function DateRangeSelect({
	className,
	jobId,
	getTooltipContainer,
	maxDay,
	target,
	note,
	nameList,
	...props
}) {
	const [selectedTime, setSelectedTime] = React.useState('latest');
	const [dateSelectorVisible, setDateSelectorVisible] = React.useState(false);
	const [dialogVisible, setDialogVisible] = React.useState(false);
	const [dateRange, setDateRange] = React.useState({
		startDate: null,
		endDate: null,
	});
	const [date, setDate] = useState([]);
	const [focusedInput, setFocuseInput] = React.useState('startDate');

	const defaultProps = React.useMemo(() => {
		return {
			autoFocusEndDate: false,
			initialStartDate: null,
			initialEndDate: null,
			startDateOffset: undefined,
			endDateOffset: undefined,
			showInputs: false,
			minDate: null,
			maxDate: dayjs().add(1, 'days'),
			renderCalendarDay: undefined,
			renderDayContents: null,
			minimumNights: 0,
			isDayBlocked: () => false,
			isDayHighlighted: () => false,
			enableOutsideDays: false,
			daysViolatingMinNightsCanBeClicked: false,
			verticalHeight: undefined,
			withPortal: false,
			initialVisibleMonth: () => dayjs().subtract(1, 'M'),
			numberOfMonths: 2,
			onOutsideClick() {},
			keepOpenOnDateSelect: false,
			renderCalendarInfo: null,
			isRTL: false,
			renderMonthText: null,
			renderMonthElement: null,
			renderKeyboardShortcutsButton: undefined,
			renderKeyboardShortcutsPanel: undefined,
			navPrev: null,
			navNext: null,
			renderNavPrevButton: null,
			renderNavNextButton: null,
			onPrevMonthClick() {},
			onNextMonthClick() {},
			monthFormat: 'YYYY年MM月',
			hideKeyboardShortcutsPanel: true,
			isOutsideRange: day =>
				maxDay
					? !isInclusivelyAfterDay(day, dayjs().add(1, 'days')) ||
					  isInclusivelyAfterDay(day, dayjs().subtract(maxDay, 'days'))
					: !isInclusivelyAfterDay(day, dayjs().add(1, 'days')),
			...props,
		};
	}, [props]);

	const handleShowDateSelector = () => setDateSelectorVisible(true);
	const handleHideDateSelector = () => setDateSelectorVisible(false);

	const handleFocusChange = focusedInput => {
		setFocuseInput(!focusedInput ? 'startDate' : focusedInput);
	};

	const handleDateChange = ({ startDate, endDate }) => {
		setDateRange({
			startDate: startDate ? dayjs(startDate).startOf('day') : null,
			endDate: endDate ? dayjs(endDate).endOf('day') : null,
		});
		setSelectedTime('scheme');
	};

	const handleSelectedTime = val => {
		setSelectedTime(val);
		if (val === 'today') {
			setDateRange({
				startDate: dayjs().startOf('day'),
				endDate: dayjs().endOf('day'),
			});
		} else if (val === 'yesterday') {
			setDateRange({
				startDate: dayjs().subtract(1, 'days').startOf('day'),
				endDate: dayjs().subtract(1, 'days').endOf('day'),
			});
		} else {
			setDateRange({});
		}
	};

	const handleDownload = () => {
		const searchString = new URLSearchParams({ job_id: jobId });
		if (selectedTime === 'latest' || selectedTime === 'previous') {
			searchString.append('report_type', selectedTime);
		} else {
			searchString.append('report_type', 'range');
			if (dateRange?.startDate) {
				searchString.append(
					'start_date',
					dayjs(dateRange?.startDate).format('YYYY-MM-DD HH:mm:ss')
				);
			}
			if (dateRange?.endDate) {
				searchString.append(
					'end_date',
					dayjs(dateRange?.endDate).format('YYYY-MM-DD HH:mm:ss')
				);
			}
		}
		return fetchjs(`/api/v2/report/download?${searchString}`)
			.then(res => {
				if (res.ok) {
					return res.blob();
				}
			})
			.then(blob => {
				const url = (window.webkitURL || window.URL).createObjectURL(blob);
				const a = document.createElement('a');
				a.href = url;
				a.download = `[${note}]ScanV安全监测报告.docx`;
				a.click();
			})
			.catch(() => {
				notification.error({
					message: `导出[${target}]ScanV安全监测报告失败`,
					placement: 'top',
					style: { width: '25rem' },
				});
			});
	};
	const onRangeChange = val => {
		console.log(val);
	};
	const recursion = obj => {
		const obj_ = obj;
		const key = Object.keys(obj_);
		if (obj_[key] && typeof obj_[key] === 'object') {
			// eslint-disable-next-line no-prototype-builtins
			if (obj_[key].hasOwnProperty('value')) {
				obj_[key] = obj_[key].value;
				// eslint-disable-next-line no-prototype-builtins
			} else {
				obj_[key] = recursion(obj_[key]);
			}
		}
		return obj_;
	};
	const [progressVisible, setProgressVisible] = React.useState(false);
	const [downloadPercent, setDownloadPercent] = React.useState(0);
	const timer = React.useRef();
	const defaultData = {
		job_ids: [],
		dateRange: [],
		download_type: 1,
	};
	const [form] = Form.useForm();
	const onValues = data => {
		const values = recursion(data);
		if (values.hasOwnProperty('job_ids')) {
			values.job_ids = values.job_ids.selectedItem.map(item => {
				return item.value;
			});
		}
		if (values.hasOwnProperty('dateRange')) {
			if (!values.dateRange) {
				values.dateRange = [];
			}
		}
		form.current.setFieldsValue(values);
	};
	const [downloadTaskId, setDownloadTaskId] = React.useState(null);
	const [downloadable, setDownloadable] = React.useState(true);
	const submitForm = () => {
		setDownloadPercent(0);
		form.current.validateFields().then(data => {
			if (!downloadable) return false;
			setDownloadable(false);
			const jobList = Object.values(nameList)
				?.flat()
				.reduce((total, item) => {
					total[item.note + '\t' + item.targetUrl] = item.id;
					return total;
				}, {});
			const downloadName = data.job_ids.map(item => {
				return item.split('\t')[0];
			});
			const job_ids = data.job_ids.map(item => {
				return jobList[item];
			});
			const date =
				data.dateRange.length > 0
					? { start_date: moment(data.dateRange[0]).format(
							'YYYY-MM-DD HH:mm:ss'
					  ), end_date: moment(data.dateRange[1]).format(
							'YYYY-MM-DD HH:mm:ss'
					  ) }
					: {};
			fetchjs(`/api/v2/report/download_task`,
				{
					method: 'POST',
					body: JSON.stringify({ job_ids: job_ids.join(','),
						download_type: data.download_type.toString(),
						report_type: Object.keys(date).length > 0 ? 'range' : 'latest',
						...date
				  })
				}
			)
				.then(res => {
					if (res.code === 200) {
						setDialogVisible(false);
						form.current.setFieldsValue(defaultData);
						form.current.resetFields();
						setProgressVisible(true);
						setDownloadable(true);
						setDownloadTaskId(res.result.download_task_id);
						timer.current = setInterval(() => {
							getProgress(
								res.result.download_task_id,
								downloadName,
								data.download_type
							);
						}, 1000);
					} else {
						setDownloadable(true);
					}
				})
				.catch(e => {
					setDownloadable(true);
					return {};
				});
		});
	};
	const getProgress = (id, name, type) => {
		fetchjs(`/api/v2/report/download_progress?download_task_id=${id}`)
			.then(res => {
				if (res.code === 200) {
					if (res.result.progress === 100) {
						setDownloadPercent(99);
						clearInterval(timer.current);
						fetch(`/api/v2/report/download_completed?download_task_id=${id}`)
							.then(res => {
								if (res.ok) {
									return res.blob();
								}
							})
							.then(blob => {
								const url = (window.webkitURL || window.URL).createObjectURL(
									blob
								);
								const a = document.createElement('a');
								if (type === 0) {
									a.download = `[${
										name[0] +
										(name.length > 1 ? '等多个资产' : '') +
										(name.length > 1 && type === 0 ? '汇总' : '')
									}]ScanV安全监测报告.docx`;
								} else {
									a.download = `[${
										name[0] +
										(name.length > 1 ? '等多个资产' : '') +
										(name.length > 1 && type === 0 ? '汇总' : '')
									}]ScanV安全监测报告.zip`;
								}
								a.href = url;
								setDownloadPercent(100);
								setTimeout(function () {
									setProgressVisible(false);
									a.click();
								}, 500);
							})
							.catch(error => {
								return {};
							});
					} else {
						setDownloadPercent(res.result.progress);
					}
				}
			})
			.catch(error => {
				setProgressVisible(false);
				clearInterval(timer.current);
				setDownloadPercent(0);
				notification.error({
					type: 'error',
					message: error.message,
				});
			});
	};
	const disableDate = current => {
		return (
			current.diff(moment(), 'days', true) >= 0 ||
			current.diff(moment().subtract(180, 'days'), 'days', true) <= 0
		);
	};

	return (
		<div className={s.container}>
			<Button
				className={cn(s.btn, className)}
				primary
				disabled={!jobId}
				onClick={() => {
					form.current.setFieldsValue(defaultData);
					setDialogVisible(true);
					setDownloadable(true);
				}}
			>
				报告下载
			</Button>
			<Dialog
				className={s.w680}
				title="报告下载"
				visible={dialogVisible}
				onhide={() => {
					form.current.setFieldsValue(defaultData);
					form.current.resetFields();
					setDialogVisible(false);
				}}
				onsubmit={submitForm}
			>
				<div className={s.dcontent}>
					<Form
						ref={form}
						initialValues={defaultData}
						onValuesChange={(newItem, allValues) => {
							onValues(newItem, allValues);
						}}
						labelCol={{ span: 4 }}
						labelAlign="right"
						wrapperCol={{ span: 20 }}
					>
						<Form.Item
							label="资产"
							name="job_ids"
							rules={[{ required: true, message: '请选择资产' }]}
						>
							<Select
								checkAll
								placeholder="请选择资产"
								multiple
								className={cn(s.w500, s.dSelect)}
								option={Object.values(nameList)
									?.flat()
									.map(item => {
										return {
											label: item.note + '\t' + item.targetUrl + (item.sourceIp ? `  (${item.sourceIp})` : ''),
											labelHtml: `<span style="width: 100px;display: inline-block;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" title='${item.note}'>${item.note}</span>
										 		<span style="width: 200px;display: inline-block;margin-left: 10px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" title='${item.targetUrl}'>${item.targetUrl}</span>
												${item.sourceIp ? `<span style="width: 100px;display: inline-block;margin-left: 10px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" title='${item.sourceIp}'>${item.sourceIp}</span>` : ''}
										 	`,
											value: item.note + '\t' + item.targetUrl,
										};
									})}
								clearable
								searchable
							/>
						</Form.Item>
						<div className={s.pr}>
							<Form.Item label="时间范围" name="dateRange">
								<Datetime
									disabledDate={disableDate}
									onCalendarChange={date => {
										if (date?.length > 0) {
											form.current.setFieldsValue({ dateRange: date });
										} else {
											form.current.setFieldsValue({ dateRange: [] });
										}
									}}
									ranges={{
										最新一次监测: [],
										今天: [moment().hours(0).minutes(0).seconds(0), moment()],
										昨天: [
											moment()
												.subtract(1, 'days')
												.hours(0)
												.minutes(0)
												.seconds(0),
											moment()
												.subtract(1, 'days')
												.hours(23)
												.minutes(59)
												.seconds(59),
										],
										最近7天: [
											moment()
												.subtract(6, 'days')
												.hours(0)
												.minutes(0)
												.seconds(0),
											moment(),
										],
									}}
									className={s.w500}
									dropdownClassName={s.z2002}
								/>
							</Form.Item>
							<span className={s.dateTip}>
								若不选时间范围，则默认下载最新一次监测结果
							</span>
						</div>
						<Form.Item label="导出方式" name="download_type">
							<Radio.Group>
								<Radio className={s.h22} value={1}>
									批量导出
								</Radio>
								<Radio className={cn(s.ml8, s.h22)} value={0}>
									合并导出
								</Radio>
							</Radio.Group>
						</Form.Item>
					</Form>
				</div>
			</Dialog>
			<Dialog
				title="提示"
				className={s.w400}
				maskClosable={false}
				visible={progressVisible}
				confirmText=""
				cancelText=""
				onhide={() => {
					setProgressVisible(false);
					clearInterval(timer.current);
					setDownloadPercent(0);
				}}
			>
				<div className={s.p24}>
					<p>正在导出报告，请稍等···</p>
					<p>进度：{downloadPercent}%</p>
					<Progress percent={downloadPercent + '%'}></Progress>
				</div>
			</Dialog>
			{/* <div className={cn(s.dateRangeSelect, { [s.show]: dateSelectorVisible })}>
				<div className={s.left}>
					<div className={s.inputContainer}>
						<Input
							className={s.input}
							value={datetime(dateRange?.startDate?.toDate())}
						/>
						<Input
							className={s.input}
							value={datetime(dateRange?.endDate?.toDate())}
						/>
					</div>
					<DayPickerRangeController
						{...defaultProps}
						startDate={dateRange?.startDate}
						endDate={dateRange?.endDate}
						onDatesChange={handleDateChange}
						focusedInput={focusedInput}
						onFocusChange={handleFocusChange}
						numberOfMonths={2}
						noBorder={true}
						maxDate={dayjs().add(1, 'days')}
					/>
				</div>
				<div className={s.right}>
					<div className={s.list}>
						{selectList.map(({ label, value }) => (
							<div
								key={value}
								onClick={() => handleSelectedTime(value)}
								className={cn(s.li, { [s.selected]: value === selectedTime })}
							>
								{label}
							</div>
						))}
					</div>
					<div className={s.btnContainer}>
						<Button
							className={s.btn}
							size="small"
							onClick={handleDownload}
							primary
						>
							确定
						</Button>
						<Button
							className={s.btn}
							onClick={handleHideDateSelector}
							size="small"
						>
							取消
						</Button>
					</div>
				</div>
			</div>
			<div
				className={cn(s.mask, { [s.show]: dateSelectorVisible })}
				onClick={handleHideDateSelector}
			/> */}
		</div>
	);
}

DateRangeSelect.propTypes = {
	className: PropTypes.string,
	jobId: PropTypes.string.isRequired,
	target: PropTypes.shape({
		host: PropTypes.string,
		protocol: PropTypes.string,
	}).isRequired,
	getTooltipContainer: PropTypes.func.isRequired,
	maxDay: PropTypes.number,
	note: PropTypes.string,
};

DateRangeSelect.defaultProps = {
	maxDay: 180,
	className: s.dateRangeSelect,
	getTooltipContainer: () => document.body,
};
